package com.southgis.ibase.sql.func;

import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.PagerUtils;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;

@Slf4j
public class DmFunc extends OracleFunc
{
	@Override
	public String charType(int len)
	{
		if(len<0 || len>8000) {//最大可以到8188
			return getDialect().getTypeName(java.sql.Types.CLOB);
		}else if(len==0) {
			String typeName=getDialect().getTypeName(java.sql.Types.VARCHAR, 1, 0, 0);
			int pos=typeName.indexOf('(');
			if(pos>0) typeName=typeName.substring(0,pos).trim();
			return typeName;
		}else {
			return getDialect().getTypeName(java.sql.Types.VARCHAR, len, 0, 0);
		}
	}
	
	//标准写法
//	@Override
//	public String binaryType(int len)
//	{
//	}
	
	@Override
	public String datetimeType()
	{
		return "DATETIME";
	}
	
	//标准类型：double precision
	//也支持Oracle的binary_double
	@Override
	public String doubleType()
	{
		return "DOUBLE PRECISION";
	}
	
	//标准写法
//	@Override
//	public String decimalType(int len,int scale)
//	{
//	}

	//标准写法
//	@Override
//	public String intType(int width)
//	{
//	}
	
	//与Oracle一致
//	@Override
//	public String notEmptyCharWhere(String fieldName)
//	{
//		return "(" + fieldName + " is not null)";
//	}
	
	//与Oracle一致
//	@Override
//	public String emptyCharWhere(String fieldName)
//	{
//		return "(" + fieldName + " is null)";
//	}

	//与Oracle一致
//	@Override
//	public String concatChar(String... charVals)
//	{
//		return "(" + String.join(" || ", charVals)+")";
//	}

	//默认格式转换与oracle不同，其他与oracle相同
	@Override
	public String getCharToDateInvoke(String charVal, int fmt)
	{
		String sql="";
		switch(fmt)
		{
		case 0: //yyyy-MM-dd HH:mm:ss
			sql="to_date("+charVal+",'yyyy-mm-dd HH24:mi:ss')";
			break;
		case 1: //yyyyMMddHHmmss
			sql="to_date("+charVal+",'yyyymmddHH24miss')";
			break;
		case 10: //yyyy-MM-dd
			sql="to_date("+charVal+",'yyyy-mm-dd')";
			break;
		case 11: //yyyyMMdd
			sql="to_date("+charVal+",'yyyymmdd')";
			break;
		default://默认格式，即不用格式串
			sql=getCastInvoke(charVal,java.sql.Types.TIMESTAMP,0,0);
			break;
		}

		return sql;
	}
	
	//标准写法
//	@Override
//	public String getYearInvoke(String dateVal)
//	{
//	}

	//标准写法
//	@Override
//	public String getDateConst(String fmtVal)
//	{
//	}
	
	//标准写法
//	@Override
//	public String getCastInvoke(String orgVal,int targetType,int length, int scale)
//	{
//	}
	
	//与Oracle一致
//	@Override
//	public String pageSql(String sql, int offset, int pageSize)
//	{
//		int max = offset + pageSize;
//
//		return "select * from ( select row_.*, rownum rownum_ from (" + sql + ") row_ "
//		 +" where rownum<=" + max + ") where rownum_>" + offset;
//	}
	
	@Override
	public String countSql(String sql)
	{
		try {
			String countSql = getDistinctContSql(sql);
			if (StringUtils.isEmpty(countSql)) {
				countSql = PagerUtils.count(sql, DbType.oracle);
			}
			return countSql;
		}catch (Exception e) {
			log.warn("生成统计数sql", e);
			return "select count(*) from ("+sql+") ct_";
		}

	}
	
	//与Oracle一致
//	@Override
//	public String sqlOfTableCount(String tableName, String schema)
//	{
//	}
	
	//与Oracle一致
//	@Override
//	public String sqlOfListTable(String name, TableTypeEnum typeEnum, String schema)
//	{
//	}

	//与Oracle一致
//	@Override
//	public String sqlOfListColumns(String tableName, String schema)
//	{
//	}

	//与Oracle一致
//	@Override
//	public String sqlOfListConstraint(ConstraintTypeEnum typeEnum, String tableName,String schema)
//	{
//	}
	
	//与Oracle一致
//	@Override
//	public List<String> sqlOfCreateTable(String tableName, String comment, List<ColumnDefine> colDef, String schema)
//	{
//	}
	
	//与Oracle一致
//	@Override
//	public String sqlOfModifyTableComment(String comment,String tableName,String schema)
//	{
//		return "COMMENT ON TABLE "+getFullTable(schema,tableName)
//				+" is '"+ConvertUtil.toSql(comment)+"'";
//	}

	@Override
	public List<String> sqlOfAddColumn(ColumnDefine colDef,String tableName, String schema)
	{
		List<String> lsSql=new ArrayList<String>();
		String sql;
		String fullTable=getFullTable(schema,tableName);
		sql="ALTER TABLE "+fullTable
				+" ADD column ("+colDef.getName()+" "+getColumnTypeString(colDef)+(colDef.isNullable()?" )":" NOT NULL)");
		lsSql.add(sql);
		
		if(!StringUtils.isEmpty(colDef.getComment())) {
			sql = addColumnComment(fullTable, colDef.getName(), colDef.getComment());
			lsSql.add(sql);
		}
		return lsSql;
	}
	
	//与Oracle一致
//	@Override
//	protected String addColumnComment(String fullTable,String colName,String comment)
//	{
//		return "COMMENT ON COLUMN "+fullTable
//				+"."+colName+" is '"+ConvertUtil.toSql(comment)+"'";
//	}
	
	@Override
	public List<String> sqlOfModifyColumn(ModifyColumnDefine colDef,String tableName, String schema)
	{
		List<String> lsSql=new ArrayList<String>();
		String sql;
		String fullTable=getFullTable(schema,tableName);
		
		if(colDef.isModifyName()) {
			sql="ALTER TABLE "+fullTable+" alter COLUMN "+colDef.getOldName()+" rename TO "+colDef.getName();
			lsSql.add(sql);
		}
		boolean setModifyNull=true;
		if(colDef.isModifyType()) {
			//以复制字段方式修改类型
			if(colDef.isByCopyModel())
			{
				String copyFiled=colDef.getName()+"_bak";
				//添加一个转换字段（如果存在这个字段时，会失败，需要用其他方式将这个备份字段删除）
				sql="ALTER TABLE "+fullTable + " ADD column ("+copyFiled+" "+getColumnTypeString(colDef)+" )";
				lsSql.add(sql);
				//将数据复制到转换字段（此时已做了字段改名，所以不用考虑oldName的问题）
				sql=String.format("update %s set %s=%s", fullTable, copyFiled, colDef.getName());
				lsSql.add(sql);
				//删除原字段
				sql=sqlOfDropColumn(colDef.getName(), fullTable, null);
				lsSql.add(sql);
				//将转换字段改名为原字段名
				sql="ALTER TABLE "+fullTable+" alter COLUMN "+copyFiled+" rename TO "+colDef.getName();
				lsSql.add(sql);
			}else {
				setModifyNull=false;
				sql="ALTER TABLE "+fullTable+" modify "+colDef.getName()+" "+getColumnTypeString(colDef);
				if(colDef.isModifyNullable()) {
					sql=sql+" "+(colDef.isNullable()?"NULL":"NOT NULL");
				}
				lsSql.add(sql);
			}
		}

		if(setModifyNull && colDef.isModifyNullable()) {
			sql="ALTER TABLE "+fullTable+" alter column "+colDef.getName()+" set "+(colDef.isNullable()?"NULL":"NOT NULL");
			lsSql.add(sql);
		}
		if(colDef.isModifyComment()) {
			sql = addColumnComment(fullTable, colDef.getName(), colDef.getComment());
			lsSql.add(sql);
		}
		return lsSql;
	}
	
	//标准写法，也兼容Oracle的语法
//	@Override
//	public String sqlOfDropColumn(String colName, String tableName, String schema)
//	{
//		return String.format("alter table %s drop column %s", getFullTable(schema,tableName),colName);
//	}

	@Override
	public String sqlOfDropPrimaryKey(String keyName, String tableName, String schema)
	{
		return sqlOfDropConstraint(keyName,tableName,schema);
	}
	
	//标准写法
//	@Override
//	public String sqlOfAddUniqueKey(String keyName, String colName, String tableName, String schema)
//	{
//	}
	
	//标准写法
//	@Override
//	public String sqlOfDropUniqueKey(String keyName, String tableName, String schema)
//	{
//	}

	//标准写法
//	@Override
//	public String sqlOfDropForeignKey(String keyName, String tableName, String schema)
//	{
//	}
	
	@Override
	public String sqlOfEnableForeignKey(String keyName, Boolean enabled, String tableName, String schema)
	{
		return "ALTER TABLE "+getFullTable(schema,tableName)
				+" MODIFY constraint "+keyName+" "+(enabled?"enable":"disable");
	}

//	/**
//	 * 重载父类的实现，针对特殊类型特殊处理
//	 */
//	@Override
//	protected String getColumnTypeString(ColumnDefine colDef)
//	{
//		String typeStr=super.getColumnTypeString(colDef);
////		int len=colDef.getLength();
////		if(colDef.getType()==ColumnTypeEnum.Json)
////		{
////			if(len==0) len=2000;
////			typeStr=charType(len);
////		}
////		else if(colDef.getType()==ColumnTypeEnum.Geometry) {
////			//定义	 point（点）,line（两点直线段）,polyline（折线）,polygon（多边形），mpolygon（空心多边形，第一部分为外边界，剩下每一块描述的是内部空心边界）,rectangle（矩形）,circle（圆）
////			//暂时定义为二进制串
////			if(len==0) len=2000;
////			typeStr=binaryType(len);
////		}
//		return typeStr;
//	}

}
